﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using CANDataIO;
using ECANPort;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using UsingEventAggregator.Core;
using Forms = System.Windows.Forms;
using HCC = HandyControl.Controls;


namespace TLDNs.ViewModels
{

    public enum EErrClass
    {
        Warning,
        Error,
    }


    public class ErrorHistoryItem : BindableBase
    {
        private int _Index;
        public int Index
        {
            get { return _Index; }
            set { SetProperty(ref _Index, value); }
        }

        private int _Count=1;
        public int Count
        {
            get { return _Count; }
            set { SetProperty(ref _Count, value); }
        }

        private DateTime _Time;
        public DateTime Time
        {
            get { return _Time; }
            set { SetProperty(ref _Time, value); }
        }
        public string DeviceName { get; set; }
        public int ErrCode { get; set; }
        public EErrClass ErrClass { get; set; }
        public string ErrName { get; set; }
        public string ErrAddInfo { get; set; }
    }

    /// <summary>
    /// TODO:确认Can直接报的故障和通过上位机报的故障是否是一样的
    /// </summary>
    public class ErrorHistoryViewModel : CanDevViewModelBase
    {

        private static string GetErrNameValue(int ErrCode)
        {
            if (ErrCode < 0 || ErrCode > 31)
                return "";

            string key = $"Err{ErrCode}_Name";
            try
            {
                string rt = $"{LangDic[key]}";
                return rt;
            }
            catch (Exception ex)
            {
                return "";
            }
        }
        private static string GetErrAddInfoValue(int ErrCode)
        {
            if (ErrCode < 0 || ErrCode > 31)
                return "";

            string key = $"Err{ErrCode}_AddInfo";
            try
            {
                string rt = $"{LangDic[key]}";
                return rt;
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public ErrorHistoryViewModel(IContainerExtension Container, IRegionManager rm, IEventAggregator ea) : base(Container, rm, ea)
        {
            _ea.GetEvent<NewErrorHistoryEvent>().Subscribe(HMI_NewErrorHistoryEvent_Sub);
            _ea.GetEvent<CanNewErrorHistoryEvent>().Subscribe(CanNewErrorHistoryEvent_Sub);


            _ea.GetEvent<IntoRootModelEvent>().Subscribe(new Action<bool>((IsRoot) =>
            {
                if (IsRoot)
                {
                    OnRootModelVisibility = Visibility.Visible;
                }
                else
                {
                    OnRootModelVisibility = Visibility.Collapsed;
                }
            }));

        }



        private static string[] SFM_DeviceNames = new string[] { "0", "1", "2" };
        /// <summary>
        /// 打开文件后或者切换文件后注册
        /// </summary>
        /// <param name="DevNames"></param>
        public static void RegeditSFMDevNames(string[] DevNames)
        {
            SFM_DeviceNames = DevNames;
        }
        /// <summary>
        /// Can 直接报的故障,按照我们自己控制器的逻辑Err32
        /// </summary>
        /// <param name="obj"></param>
        private void CanNewErrorHistoryEvent_Sub((int ErrCode, int DevIndex) pa)
        {
            ErrorHistoryItem err1 = new ErrorHistoryItem();
            err1.Index = ErrDataList.Count;
            err1.Time = DateTime.Now;
            if (SFM_DeviceNames != null && SFM_DeviceNames.Length > pa.DevIndex)
                err1.DeviceName = SFM_DeviceNames[pa.DevIndex];
            else
            {
                err1.DeviceName = pa.DevIndex.ToString();
            }
            err1.ErrCode = pa.ErrCode;
            err1.ErrClass = (EErrClass)CanNewErrorHistoryEvent.EErrClass;
            err1.ErrName = CanNewErrorHistoryEvent.ErrName;
            err1.ErrAddInfo = CanNewErrorHistoryEvent.ErrAddInfo;
            err1.Count = 1;
            bool IsContains = false;
            int ContainsIndex = -1;
            for (int i = 0; i < ErrDataList.Count; i++)
            {
                if (ErrDataList[i].ErrCode == pa.ErrCode && ErrDataList[i].DeviceName == SFM_DeviceNames[pa.DevIndex])
                {
                    IsContains = true;
                    ContainsIndex = i;
                    break;
                }
            }
            if (IsContains)
            {
                App.UIDispatcherDoAction(() =>
                {
                    ErrDataList[ContainsIndex].Time = DateTime.Now;
                    ErrDataList[ContainsIndex].Count += 1;
                });

            }
            else
            {
                App.UIDispatcherDoAction(() =>
                {
                    ErrDataList.Add(err1);
                });

            }

        }

        private ObservableCollection<ErrorHistoryItem> _ErrDataList = new ObservableCollection<ErrorHistoryItem>();
        public ObservableCollection<ErrorHistoryItem> ErrDataList
        {
            get { return _ErrDataList; }
            set { SetProperty(ref _ErrDataList, value); }
        }

      

        protected override void SFMFileIsReLoaded()
        {

        }

        private void HMI_NewErrorHistoryEvent_Sub((uint Err32, int DevIndex) pa)
        {
            bool[] errs = PubMod.Uint32ToBitArry(pa.Err32);
            for (int i = 0; i < errs.Length; i++)
            {
                if (errs[i])
                {
                    HMI_NewErrorHistoryIndex((i, pa.DevIndex));
                }
            }
        }

        private void HMI_NewErrorHistoryIndex((int Err32Index, int DevIndex) pa)
        {
            ErrorHistoryItem err1 = new ErrorHistoryItem();
            err1.Index = ErrDataList.Count;
            err1.Time = DateTime.Now;
            if (SFM_DeviceNames != null && SFM_DeviceNames.Length > pa.DevIndex)
                err1.DeviceName = SFM_DeviceNames[pa.DevIndex];
            else
            {
                err1.DeviceName = pa.DevIndex.ToString();
            }
            err1.ErrCode = pa.Err32Index;
            err1.ErrClass = EErrClass.Error;
            err1.ErrName = GetErrNameValue(pa.Err32Index);
            err1.ErrAddInfo = GetErrAddInfoValue(pa.Err32Index);
            err1.Count = 1;

            bool IsContains = false;
            int ContainsIndex = -1;
            for (int i = 0; i < ErrDataList.Count; i++)
            {
                if (ErrDataList[i].ErrCode == pa.Err32Index && ErrDataList[i].DeviceName == SFM_DeviceNames[pa.DevIndex])
                {
                    IsContains = true;
                    ContainsIndex = i;
                    break;
                }
            }
            if (IsContains)
            {
                App.UIDispatcherDoAction(() =>
                {
                    ErrDataList[ContainsIndex].Time = DateTime.Now;
                    ErrDataList[ContainsIndex].Count += 1;
                });

            }
            else
            {
                App.UIDispatcherDoAction(() =>
                {
                    ErrDataList.Add(err1);
                });

            }




        }


        public DelegateCommand<double?> VartualErrorCommand => new DelegateCommand<double?>(VartualErrorCommand_Sub);
        private void VartualErrorCommand_Sub(double? err)
        {
            if (err != null)
            {
                uint err1 = (uint)err.Value;
                _ea.GetEvent<NewErrorHistoryEvent>().Publish((err1, 0));
            }
        }

        public DelegateCommand ExportErrHistoryCommand => new DelegateCommand(ExportErrHistoryCommand_Sub);
        private void ExportErrHistoryCommand_Sub()
        {
            if (ErrDataList.Count > 0)
            {
                Forms.SaveFileDialog save = new Forms.SaveFileDialog();
                save.Filter = $"Excel{LangDic["File"]}(*.xls)|*.xls";
                save.Title = $"{LangDic["SaveFileTitle"]}";
                save.FileName = "ErrHistoryExport_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-sss.fff") + ".xls";
                if (save.ShowDialog() == Forms.DialogResult.OK)
                {
                    List<string> Headers = new List<string>();
                    Collection<List<string>> data = new Collection<List<string>>(); ;
                    Headers.Add($"{LangDic["Index"]}");
                    Headers.Add($"{LangDic["TimeString"]}");
                    Headers.Add($"{LangDic["DeviceName"]}");
                    Headers.Add($"{LangDic["ErrCode"]}");
                    Headers.Add($"{LangDic["ErrClass"]}");
                    Headers.Add($"{LangDic["ErrName"]}");
                    Headers.Add($"{LangDic["ErrAddInfo"]}");

                    List<string> item = new List<string>();
                    for (int i = 0; i < ErrDataList.Count; i++)
                    {
                        item = new List<string>();
                        item.Add(ErrDataList[i].Index.ToString());
                        item.Add(ErrDataList[i].Time.ToString());
                        item.Add(ErrDataList[i].DeviceName);
                        item.Add(ErrDataList[i].ErrCode.ToString());
                        item.Add(ErrDataList[i].ErrClass.ToString("F"));
                        item.Add(ErrDataList[i].ErrName);
                        item.Add(ErrDataList[i].ErrAddInfo);
                        data.Add(item);
                    }

                    Task.Run(() =>
                    {
                        Excel2007 excel = new Excel2007();
                        excel.Save(save.FileName, Headers, data, "Sheet1", new Action<double>(UpdateErrHisDataExport),
                            Properties.Settings.Default.ExportReadOnly);
                        HCC.Growl.Info($"{LangDic["ExportOk"]}");
                        if (OnExportAutoClear)
                        {
                            App.UIDispatcherDoAction(() => { ErrDataList.Clear(); });
                        }
                    });
                }
            }
            else
            {
                HCC.Growl.Info($"{LangDic["NoDateExport"]}");
            }
        }

        private bool _ExportAutoClear;
        public bool OnExportAutoClear
        {
            get { return _ExportAutoClear; }
            set { SetProperty(ref _ExportAutoClear, value); }
        }

        private void UpdateErrHisDataExport(double pc)
        {
            int DataExportPc = (int)Math.Round(pc * 100, 1);
        }

        private Visibility _OnRootModelVisibility = Visibility.Collapsed;
        public Visibility OnRootModelVisibility
        {
            get { return _OnRootModelVisibility; }
            set
            {
                SetProperty(ref _OnRootModelVisibility, value);
            }
        }

    }
}
